const express = require('express')
const expressApp = express()

const path = require('path')
const fs = require('fs')
const readline = require('readline')

// 插件入口
class MyCustomPlugin {
  constructor(config, options) {
    this.config = config // config.yml文件下middlewares配置
    this.options = options // verdaccio实例的配置
  }

  // 注册中间件
  register_middlewares(app, auth, storage) {
    /**
     * logs_path verdaccio 操作日志路径
     * storage_path .verdaccio-db.json本地包数据存储文件(storage可以直接register_middlewares接参storage上直接获取)
     */
    const { logs_path, storage_path } = this.config

    // 日志文件路径
    const logFile = 'E:\\CET2025\\verdaccio\\logs\\3th-verdaccio-out.log'

    // 私有化包列表
    const storagePlugin_list = storage?.localStorage?.storagePlugin?.data?.list

    // listen
    const listen_path = storage?.config?.listen

    /**
     * ### 添加自定义路由
     * @description: 自定义页面路由
     * /custom-page
     */
    app.get('/custom-download-logs', (req, res) => {
      const filePath = path.join(__dirname, 'static', 'custom-download-logs.html')
      fs.readFile(filePath, 'utf8', (err, data) => {
        if (err) {
          res.status(500).send('Error loading custom page')
        } else {
          res.send(data)
        }
      })
    })

    /**
     * ### 获取pm2 verdaccio日志
     * @description: verdaccio由pm2 启动, 所以需要读取pm2 verdaccio日志, 用于解析下载日志
     * 需考虑日志文件过大使用日志轮转分割存储
     */
    app.get('/api/getPm2VerdaccioLogs', async (req, res) => {
      const logs = await getPm2VerdaccioLogs()

      const filterLogs = (logs) => {
        new Promise((resolve, reject) => {
          const packageTotal = []
          const packageDetail = {}

          const inputFilePath = 'E:\\CET2025\\verdaccio\\storage\\.verdaccio-db.json'
          // 读取 JSON 文件
          fs.readFile(inputFilePath, 'utf8', (err, data) => {
            if (err) {
              console.error('读取文件时出错:', err)
              return
            }

            try {
              // 解析 JSON 数据
              const packages = JSON.parse(data)

              const packageArray = []
              const packageList = []

              packages.list.map((item) => {
                packageList.push(item)
                packageArray.push({
                  name: item,
                  downloadNum: logs[item]
                })
              })

              packageList.forEach((pkg) => {
                let totalDownloads = 0

                packageDetail[pkg] = {
                  total: 0,
                  details: {}
                }

                for (const key in logs) {
                  if (logs.hasOwnProperty(key)) {
                    // Check if the key is exactly the package name or contains the package name and ends with .tgz
                    if (key === pkg || (key.includes(pkg) && key.endsWith('.tgz'))) {
                      totalDownloads += logs[key]
                      packageDetail[pkg].details[key] = logs[key]
                    }
                  }
                }
                packageDetail[pkg].total = totalDownloads
                // packageTotal[pkg] = totalDownloads
                packageTotal.push({
                  packageName: pkg,
                  version: '',
                  value: totalDownloads
                })
              })
            } catch (parseErr) {
              console.error('解析 JSON 数据时出错:', parseErr)
            }

            console.log('处理成功', packageTotal)
            resolve({ packageTotal: packageTotal, packageDetail: packageDetail })
            res.send({
              code: 0,
              msg: '读取日志记录成功',
              data: {
                // logs: logs,
                downloadLogs: {
                  packageTotal: packageTotal,
                  packageDetail: packageDetail
                },
                config: this.config,
                options: this.options,
                auth: auth,
                storage: storage
              }
            })
          })
        })
      }

      filterLogs(logs)
    })

    /**
     * ### 根据配置的日志文件路径读取日志, 用于解析下载日志
     * @description: 日志文件过大采取流式读取
     * @returns
     */
    const getPm2VerdaccioLogs = () => {
      return new Promise((resolve, reject) => {
        try {
          // 创建可读流
          const fileStream = fs.createReadStream(logFile, { encoding: 'utf-8' })

          // 创建逐行读取接口
          const rl = readline.createInterface({
            input: fileStream,
            crlfDelay: Infinity // 支持 Windows 和 Linux/macOS 的换行符
          })

          // 统计下载次数
          const downloadStats = {}

          rl.on('line', (line) => {
            // 匹配 GET 请求
            const match = line.match(/requested 'GET \/([^']+)'/)
            if (match) {
              const packageName = decodeURIComponent(match[1])
              downloadStats[packageName] = (downloadStats[packageName] || 0) + 1
            }
          })

          rl.on('close', () => {
            resolve(downloadStats)
          })
        } catch {
          reject('Error reading log file')
        }
      })
    }
    console.log(`Plugin started successfully `)
    console.log(`Custom plugin page registered at ${listen_path}/custom-download-logs`)
  }
}

module.exports = (config, options) => new MyCustomPlugin(config, options)
